package dominio;
import java.util.*;

public final class Partida {
    
    //Atributos    
    private Ficha[][] tablero;
    private Tablero[] paneles;    
    private Jugador jugador1;
    private Jugador jugador2;
    private int baseTablero;
    private int largoLinea;    
    private boolean esEscalera;
    
    
    //Métodos de acceso y modificación
    public Tablero[] getPaneles(){
        return paneles;
    }
    
    public Tablero getTablero(int numeroTablero) {        
        return paneles[numeroTablero];
    }
    
    public Ficha[][] getTablero() {
        actualizarTablero();
        return tablero;
    }
    
    public Jugador getJugador1() {
        return jugador1;
    }

    public void setJugador1(Jugador jugador1) {
        this.jugador1 = jugador1;
    }

    public Jugador getJugador2() {
        return jugador2;
    }

    public void setJugador2(Jugador jugador2) {
        this.jugador2 = jugador2;
    }
    
    public int getBaseTablero() {
        return baseTablero;
    }

    public void setBaseTablero(int baseTablero) {
        this.baseTablero = baseTablero;
    }

    public int getLargoLinea() {
        return largoLinea;
    }

    public void setLargoLinea(int largoLinea) {
        this.largoLinea = largoLinea;
    }

    public boolean getEsEscalera() {
        return esEscalera;
    }

    public void setEsEscalera(boolean esEscalera) {
        this.esEscalera = esEscalera;
    }

    
    //Constructores
    public Partida(Jugador jugador1, Jugador jugador2, int baseTablero, int largoLinea) {
        this.jugador1 = jugador1;
        this.jugador2 = jugador2;
        this.baseTablero = baseTablero;
        this.largoLinea = largoLinea;
    }

    public Partida(int baseTablero, boolean esEscalera) {             
       paneles = new Tablero[baseTablero - 1];
       tablero = new Ficha[baseTablero][baseTablero];
       setBaseTablero(baseTablero);
       crearTablero(baseTablero, esEscalera);
       setEsEscalera(esEscalera);
    }
            
    
    //Método que actualiza el tablero que se mostrará por pantalla
    private void actualizarTablero(){
        int panelActual = 0;
        for (int i = 0; i < tablero.length; i++) {
            for (int j = 0; j < tablero[0].length; j++) {
                panelActual = obtenerNivel(i, j);
                char colorFicha = paneles[panelActual - 1].getFicha(i, j);  //TABLERO NO TIENE VARIABLE FICHA
                Ficha ficha = new Ficha(colorFicha, panelActual);
                tablero[i][j] = ficha;
            }
        }
    }
    
    
    //Método que crea el tablero
    private void crearTablero(int tamaño, boolean escalera) {
        Posicion pos = new Posicion();
        //Indico el tamaño del tablero
        Tablero.setTamañoPadre(tamaño);
        Tablero base = new Tablero(tamaño, pos, escalera);
        paneles = obtenerPaneles(base, paneles, 0);
    }
    
    
    //Método que genera los tableros, uno encima del otro
    private Tablero[] obtenerPaneles(Tablero base, Tablero[] paneles, int nivel) {
        if (base != null) {
            paneles[nivel] = base;
            paneles = obtenerPaneles(base.getPanelSuperior(), paneles, nivel + 1);
        }
        return paneles;
    }   
    
    
    /*Método usado para verificar si en un sentido se formo una linea
    @param ficha: color de la ficha a verificar
    @param pos: lugar del tablero donde iniciar la busqueda
    @param sentido: dirección a comprobar*/
    private boolean verificaLinea(char ficha, Posicion pos, Posicion sentido) {
        boolean verifica = true;
        for (int i = 1; i < 4; i++) {
            int fila = pos.getFila() + sentido.getFila() * i;
            int columna = pos.getColumna() + sentido.getColumna() * i;
            //Verifico que no salga del tablero
            if (fila >= 0 && columna >= 0 && fila < tablero.length && columna < tablero[0].length
                    && tablero[fila][columna].getColorFicha() != ficha) {
                verifica = false;
            }
        }
        return verifica;
    }    
    
    
    /*Método que verifica si el jugador gano la partida completando una linea
    @param jugador: indica el jugador para determinaar si gano
    @return retorna true si gano y false en caso contrario*/
    public boolean ganoJugador(Jugador jugador) {
        boolean gano = false;
        for (int i = 0; i < tablero.length; i++) {
            for (int j = 0; j < tablero[0].length; j++) {
                //Si es la ficha que busco
                if (tablero[i][j].getColorFicha() == jugador.getFicha().getColorFicha()) {
                    //Compruebo direcciones
                    for (int k = i; k <= i + 1; k++) {
                        for (int l = j - 1; l <= j + 1; l++) {
                            //Verifico si son la misma ficha y si no sale del tablero
                            if ((i != k && j != l) && l > 0 && k < tablero.length && l < tablero[0].length
                                    && tablero[i][j].getColorFicha() == tablero[k][l].getColorFicha()) {
                                Posicion sentido = new Posicion();
                                sentido.setFila(k - i);
                                sentido.setColumna(l - j);
                                gano = verificaLinea(jugador.getFicha().getColorFicha(), new Posicion(i, j), sentido);
                                if (gano) //<--cambiar
                                {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }

        return false;
    }
    
    
    //Método que obtiene en qué tablero se encuentra una ficha
    public int obtenerNivel(int fila, int columna) {
        int nivel = 0;
        //Recorro paneles hasta encontrar el primero que este en esa pos
        int i = getPaneles().length;
        while (i > 0 && nivel == 0) {
            Posicion posicion = getTablero(i - 1).getPosicionPadre();
            int filaPadre = posicion.getFila();
            int columnaPadre = posicion.getColumna();
            if (fila >= filaPadre && columna >= columnaPadre
                    && fila <= filaPadre + Tablero.getTamañoPadre() - i
                    && columna <= filaPadre + Tablero.getTamañoPadre() - i) {
                nivel = i;
            }
            i--;
        }
        return nivel;
    }
}